package com.lnsf.bookstore.system.schedule.service.impl;


import com.github.pagehelper.PageInfo;
import com.lnsf.bookstore.system.schedule.service.ScheduleJobService;
import com.lnsf.bookstore.system.schedule.vo.ScheduleJob;
import org.apache.commons.lang.StringUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.matchers.NameMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService{
	@Autowired
    private Scheduler scheduler;

	@Override
	public ScheduleJob getJobDetails(String name, String group) {
		JobKey jobKey = new JobKey(name, group);
		ScheduleJob scheduleJob = null;
		try{
			JobDetail jobDetail = scheduler.getJobDetail(jobKey);
			if(jobDetail != null){
				scheduleJob = new ScheduleJob();
				scheduleJob.setName(name);
				scheduleJob.setGroup(group);
				scheduleJob.setDescription(jobDetail.getDescription());
				JobKey jk = jobDetail.getKey();
				List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jk);
				for(Trigger trigger : triggers){
					Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
					scheduleJob.setStatus(triggerState.name());
					if(trigger instanceof SimpleTrigger){
						SimpleTrigger simpleTrigger = (SimpleTrigger) trigger;
						scheduleJob.setDescription("仅执行一次");
						scheduleJob.setDescription(simpleTrigger.getDescription());
					}
					if(trigger instanceof CronTrigger){
						CronTrigger cron = (CronTrigger) trigger;
						scheduleJob.setCronExpression(cron.getCronExpression());
						scheduleJob.setDescription(cron.getDescription() == null ? ("触发器:" + trigger.getKey()) : cron.getDescription());
					}
					scheduleJob.setClassName(jobDetail.getJobClass().getName());
					scheduleJob.setMethodName(((ScheduleJob)jobDetail.getJobDataMap().get("scheduleJob")).getMethodName());
				}
			}

		}catch (Exception e){
			throw new RuntimeException("查找任务详情发生未知异常：" + e.getMessage());
		}
		return scheduleJob;
	}

	@Override
	public PageInfo<ScheduleJob> queryList(ScheduleJob scheduleJob) {
		List<ScheduleJob> scheduleJobList = new ArrayList<ScheduleJob>();
		GroupMatcher<JobKey> groupMatcher = null;
		NameMatcher<JobKey> nameMatcher = null;
		if(StringUtils.isNotBlank(scheduleJob.getName())){
			nameMatcher.jobNameContains(scheduleJob.getName());
		}
		if(StringUtils.isNotBlank(scheduleJob.getGroup())){
			groupMatcher = groupMatcher.jobGroupContains(scheduleJob.getGroup());
		}else{
		    groupMatcher = groupMatcher.anyJobGroup();
		}
		try {
			Set<JobKey> jobKeys = scheduler.getJobKeys(groupMatcher);
			for (JobKey jobKey : jobKeys){
				List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
				for (Trigger trigger : triggers){
					ScheduleJob scheduleJob_instance =  new ScheduleJob();
					scheduleJob_instance.setName(jobKey.getName());
					scheduleJob_instance.setGroup(jobKey.getGroup());
					Trigger.TriggerState status = scheduler.getTriggerState(trigger.getKey());
					scheduleJob_instance.setStatus(status.name());
					//获取要执行的定时任务类名
					JobDetail jobDetail = scheduler.getJobDetail(jobKey);
					scheduleJob_instance.setClassName(jobDetail.getJobClass().getName());
					ScheduleJob sj = (ScheduleJob) jobDetail.getJobDataMap().get("scheduleJob");
					scheduleJob_instance.setMethodName(sj.getMethodName());
					scheduleJob_instance.setDescription(jobDetail.getDescription());
					//判断trigger
					if(trigger instanceof SimpleTrigger){
						SimpleTrigger simpleTrigger = (SimpleTrigger) trigger;
						if(simpleTrigger.getRepeatCount() == 0 && simpleTrigger.getRepeatInterval() == 0){
							continue;
						}
						scheduleJob_instance.setCronExpression("重复次数:"+ (simpleTrigger.getRepeatCount() == -1 ?
								"无限" : simpleTrigger.getRepeatCount()) + ",重复间隔:" + (simpleTrigger.getRepeatInterval() / 1000L));
						scheduleJob_instance.setDescription(simpleTrigger.getDescription());
					}
					if(trigger instanceof  CronTrigger){
						CronTrigger cronTrigger = (CronTrigger) trigger;
						scheduleJob_instance.setCronExpression(cronTrigger.getCronExpression());
						scheduleJob_instance.setDescription(cronTrigger.getDescription() == null ? ("触发器:" + trigger.getKey()) : cronTrigger.getDescription());
					}
					scheduleJobList.add(scheduleJob_instance);
				}
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		return new PageInfo<ScheduleJob>(scheduleJobList);
	}

	@Override
	public boolean add(ScheduleJob scheduleJob) {
		Class job = null;
		try {
			job = Class.forName(scheduleJob.getClassName());
		} catch (ClassNotFoundException e) {
			new RuntimeException(scheduleJob.getClassName()+"任务类没找到，请确定该类是否存在！");
		}
		JobKey jobKey = new JobKey(scheduleJob.getName(),scheduleJob.getGroup());
		try {
			if(scheduler.checkExists(jobKey)){
                throw new RuntimeException(jobKey.getGroup()+"-【"+jobKey.getName()+"】任务已存在，不能录入重复任务名称！");
            }
		} catch (SchedulerException e) {
			throw new RuntimeException("无法确认任务唯一性，请稍候再试！");
		}
		//requestRecovery指示调度程序是否遇到“恢复”或“故障转移”情况时是否应该重新执行作业。
		//storeDurably作业是否应在孤立后保持存储（没有触发器指向它）。
		JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(jobKey).requestRecovery(true)
				.withDescription(scheduleJob.getDescription())
				.storeDurably(true)
				.build();
		jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
		try {
		//此处可以设计判断是哪一种触发器，后续开发
		//表达式调度构建器
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()).withMisfireHandlingInstructionDoNothing();
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getName(),scheduleJob.getGroup())
				.withSchedule(scheduleBuilder)
				.withDescription(scheduleJob.getDescription())
				.build();
		scheduler.scheduleJob(jobDetail,trigger);
		scheduler.pauseJob(jobKey);
		} catch (SchedulerException e) {
			throw new RuntimeException("添加定时调度任务异常："+e.getMessage());
		}
		return true;
	}

	@Override
	public void update(ScheduleJob scheduleJob) throws SchedulerException, ClassNotFoundException {
		TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getName(),scheduleJob.getGroup());
		Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
		CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
		boolean pauseFlag = false;
		if("NORMAL".equals(triggerState.name())||"BLOCKED".equals(triggerState.name())){
			cronScheduleBuilder = cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
		}else {
			cronScheduleBuilder = cronScheduleBuilder.withMisfireHandlingInstructionDoNothing();
			pauseFlag = true;
		}
		Class<Job> jobClass = (Class<Job>) Class.forName(scheduleJob.getClassName());
		JobDetail jobDetail = JobBuilder.newJob(jobClass)
				.withDescription(scheduleJob.getDescription())
				.withIdentity(scheduleJob.getName(),scheduleJob.getGroup())
				.requestRecovery(true)
				.storeDurably(true)
				.build();
		jobDetail.getJobDataMap().put("scheduleJob",scheduleJob);
		scheduler.addJob(jobDetail,true);
		CronTrigger cronTrigger = TriggerBuilder.newTrigger()
				.withIdentity(triggerKey)
				.withSchedule(cronScheduleBuilder)
				.withDescription(scheduleJob.getDescription())
				.build();
		scheduler.rescheduleJob(triggerKey,cronTrigger);
		if(pauseFlag||"COMPELTE".equals(triggerState.name())){
			scheduler.pauseTrigger(triggerKey);
		}

	}

	@Override
	public void delete(String name, String group) {

	}

	@Override
	public void runNow(String name, String group) {
		JobKey jobKey = JobKey.jobKey(name, group);
		try {
			scheduler.triggerJob(jobKey);
		} catch (SchedulerException e) {
			//log.error("立即执行一次定时任务异常：",e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public void pause(String name, String group) {
		JobKey key = new JobKey(name, group);
		try {
			scheduler.pauseJob(key);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void resume(String name, String group) {
		JobKey key = new JobKey(name,group);
		try {
			scheduler.resumeJob(key);
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void startSchedule() {

	}

	@Override
	public void shutdownSchedule() {

	}

	@Override
	public boolean checkExist(String name, String group) {
		JobKey jobKey=new JobKey(name, group);
		try {
			return scheduler.checkExists(jobKey);
		} catch (SchedulerException e) {
			//log.error("检查任务是否已存在异常：",e);
			throw new RuntimeException(e);
		}
	}
}
